﻿package chenji.moreitemfunapi.textures;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Collection;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import com.google.common.base.Charsets;

import chenji.moreitemfunapi.MifAPI;
import chenji.moreitemfunapi.textures.info.ArmorInfo;
import chenji.moreitemfunapi.textures.info.TextureInfo;

public class TexturesSpawner implements Runnable {
	private Collection<TextureInfo> infos;
	private static final File root = new File(MifAPI.getMDataFolder() + "/textures");
	private static File packFile = new File(MifAPI.getMDataFolder() + "/pack.zip");

	public TexturesSpawner(Collection<TextureInfo> infos) {
		this.infos = infos;
	}

	private void writeMcMeta(ZipOutputStream stream) {
		try (ByteArrayOutputStream pouta = new ByteArrayOutputStream(); OutputStreamWriter w = new OutputStreamWriter(pouta, Charsets.UTF_8); BufferedWriter wr = new BufferedWriter(w);) {
			stream.putNextEntry(new ZipEntry("pack.mcmeta"));
			wr.write("{");
			wr.newLine();
			wr.write("  \"pack\": {");
			wr.newLine();
			wr.write("    \"pack_format\": 2,");
			wr.newLine();
			wr.write("    \"description\": \"§aMoreItemFun材质包\"");
			wr.newLine();
			wr.write("  }");
			wr.newLine();
			wr.write("}");
			wr.newLine();
			wr.flush();
			w.flush();
			wr.close();
			w.close();
			stream.write(pouta.toByteArray());
			stream.closeEntry();
		} catch (IOException e) {

		}
	}

	private File getImageFile(String name) {
		return new File(root + "/" + name + ".png");
	}

	private boolean writeImages(TextureInfo info, ZipOutputStream stream) {
		for (String s : info.getAlreadUpdatedTextures()) {
			if (!this.writeImage(info, s, stream)) {
				return false;
			}
		}
		return true;
	}

	private boolean writeImage(TextureInfo info, String name, ZipOutputStream stream) {
		File file = this.getImageFile(info.getImageName(name));
		if (!file.exists()) {
			return false;
		}
		try (FileInputStream in = new FileInputStream(file)) {
			stream.putNextEntry(new ZipEntry(this.getImageFile(info.getImageName(name), info.getPluginName())));
			int size = in.available();
			byte[] data = new byte[size];
			in.read(data);
			stream.write(data);
			stream.closeEntry();
			return true;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	@SuppressWarnings("deprecation")
	private boolean writeProperties(TextureInfo info, ZipOutputStream stream) {
		String propname = info.getPropertiesFileName();
		String propfile = this.getPropertiesFile(info.getPluginName(), propname);
		try (ByteArrayOutputStream pout = new ByteArrayOutputStream();) {
			info.getProperties().save(pout, "");
			stream.putNextEntry(new ZipEntry(propfile));
			stream.write(pout.toByteArray());
			stream.closeEntry();
			pout.flush();
			if (info instanceof ArmorInfo) {
				ArmorInfo armor = (ArmorInfo) info;
				armor.getItemProperties().save(pout, "");
				String armorfile = this.getPropertiesFile(armor.getPluginName(), armor.getItemPropName());
				stream.putNextEntry(new ZipEntry(armorfile));
				stream.write(pout.toByteArray());
				stream.closeEntry();
				pout.flush();
			}
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	private boolean writeInfo(TextureInfo info, ZipOutputStream stream) throws IOException {
		if (!info.isDone()) {
			return false;
		}
		if (!this.writeImages(info, stream)) {
			return false;
		}
		if (!(this.writeProperties(info, stream))) {
			return false;
		}
		return true;

	}

	@Override
	public void run() {
		try (FileOutputStream out = new FileOutputStream(packFile); ZipOutputStream stream = new ZipOutputStream(out);) {
			this.checkPath();
			stream.setLevel(0);
			this.writeMcMeta(stream);
			for (TextureInfo info : this.infos) {
				this.writeInfo(info, stream);
			}
			stream.flush();
			MifAPI.getTexturesManager().setDone();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	private String getImageFile(String name, String pluginname) {
		return "assets/minecraft/mcpatcher/cit/moreitemfun/" + pluginname + "/" + name + ".png";
	}

	private String getPropertiesFile(String plname, String propname) {
		return "assets/minecraft/mcpatcher/cit/moreitemfun/" + plname + "/" + propname + ".properties";
	}

	private void checkPath() throws IOException {
		if (TexturesSpawner.packFile.exists()) {
			TexturesSpawner.packFile.delete();
		}

		TexturesSpawner.packFile.createNewFile();

	}

}
